﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Library.IniFiles;

namespace iNotesNotification
{
    public class iNotesConfig
    {
        private const string FIREFOX_PATH = @"{PROGRAM_FILES}\Mozilla Firefox\firefox.exe";
        private const string CHROME_PATH = @"{DRIVE}\Documents and Settings\{WINDOWS_USER}\Local Settings\Application Data\Google\Chrome\Application\chrome.exe";
        private const string IEXPLORE_PATH = @"{PROGRAM_FILES}\Internet Explorer\iexplore.exe";

        private const string MAIL_DETAIL_ULTRALITE = "/(${FOLDER})/{EMAIL_UNIQUEID}/?OpenDocument&Form=m_DocumentRead";
        private const string MAIL_DETAIL_WEBMAIL = "/(${FOLDER})/{EMAIL_UNIQUEID}/?OpenDocument&ui=webmail";
        private const string MAIL_DETAIL_INOTES = "/(${FOLDER})/{EMAIL_UNIQUEID}/?OpenDocument&ui=inotes";

        private const string MAIL_LIST_ULTRALITE = "/iNotes/Mail/?OpenDocument&Form=m_MailView&PresetFields=FolderName;(${FOLDER})";
        private const string MAIL_LIST_WEBMAIL = "?OpenDatabase&ui=webmail";
        private const string MAIL_LIST_INOTES = "?OpenDatabase&ui=inotes";
        
        private static iNotesConfig _instance;
        private FileInfo _confFile;
        private string _login = "notes.user.id";
        private string _password = "";
        private string _interface = "xml";
        private int _mailCheckInterval = 60;
        private int _daysToRetrieve = 7;
        private int _countToRetrieve = 0;
        private bool _startOnApplicationStartup = false;
        private string _notesFileUrl = "https://inotes-hostname.com/mail/{USERID}.nsf";
        private string _xmlUrlSuffix = "/(${FOLDER})?ReadViewEntries&KeyType=time&StartKey={START_TIME}&UntilKey={END_TIME}";
        private string _htmlUrlSuffix = "/iNotes/Mail/?OpenDocument&Form=m_MailView&PresetFields=FolderName;(${FOLDER})&Start={START}&Count={COUNT}";
        private string _viewMailUrlSuffix = "/{EMAIL_UNIQUEID}/?OpenDocument&Form=m_DocumentRead";
        private string _soundPath = "";
        private string _browserOverrideExePath = "";
        private string _ui = "webmail";
        private string _browser = "ie";

        public static iNotesConfig Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new iNotesConfig();
                }
                return _instance;
            }
        }

        public static void Refresh() { _instance = null; }

        protected iNotesConfig()
        {
            try
            {
                _confFile = new FileInfo(iNotesController.AssemblyLocation.FullName + ".ini");

                if (_confFile.Exists) Load();
            }
            catch (Exception) { }
        }

        public string EmailListUrl(string folder)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(this.NotesFileUrl);

            switch (NotesUI[0])
            {
                case 'w':
                    sb.Append(MAIL_LIST_WEBMAIL);
                    break;
                case 'i':
                    sb.Append(MAIL_LIST_INOTES);
                    break;
                case 'u':
                default:
                    sb.Append(MAIL_LIST_ULTRALITE);
                    break;
            }

            string url = sb.ToString();

            url = url
                .Replace("{FOLDER}", folder)
                .Replace("{USERID}", this.Login.Replace(".", "_"));

            return url;
        }

        public string EmailDetailUrl(string folder, string emailId)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(this.NotesFileUrl);

            switch (NotesUI[0])
            {
                case 'w':
                    sb.Append(MAIL_DETAIL_WEBMAIL);
                    break;
                case 'i':
                    sb.Append(MAIL_DETAIL_INOTES);
                    break;
                case 'u':
                default:
                    sb.Append(MAIL_DETAIL_ULTRALITE);
                    break;
            }

            string url = sb.ToString();

            url = url
                .Replace("{FOLDER}", folder)
                .Replace("{EMAIL_UNIQUEID}", emailId)
                .Replace("{USERID}", this.Login.Replace(".", "_"));

            return url;
        }

        public bool IsBrowserOverridden
        {
            get
            {
                return (!string.IsNullOrEmpty(BrowserOverrideExePath));
            }
        }

        public string BrowserPath
        {
            get
            {
                string browserPath = null;
                if (!string.IsNullOrEmpty(BrowserOverrideExePath))
                {
                    browserPath = BrowserOverrideExePath;
                }
                else
                {
                    switch (_browser[0])
                    {
                        case 'c':
                            browserPath = CHROME_PATH;
                            break;
                        case 'f':
                            browserPath = FIREFOX_PATH;
                            break;
                        case 'i':
                        default:
                            browserPath = IEXPLORE_PATH;
                            break;
                    }
                }

                string hd = Environment.GetEnvironmentVariable("HOMEDRIVE"),
                    pf = Environment.GetEnvironmentVariable("PROGRAMFILES"),
                    user = Environment.GetEnvironmentVariable("USERNAME");

                browserPath = browserPath
                    .Replace("{DRIVE}", hd)
                    .Replace("{PROGRAM_FILES}", pf)
                    .Replace("{WINDOWS_USER}", user);

                return browserPath;
            }
        }

        public string Login
        {
            get
            {
                return _login;
            }
            set
            {
                _login = value ?? "";
            }
        }

        public string Password
        {
            get
            {
                return _password;
            }
            set
            {
                _password = value ?? "";
            }
        }

        public string Browser
        {
            get
            {
                return _browser;
            }
            set
            {
                _browser = value ?? "";
            }
        }

        public string BrowserOverrideExePath
        {
            get
            {
                return _browserOverrideExePath;
            }
            set
            {
                _browserOverrideExePath = value ?? "";
            }
        }

        public string SoundPath
        {
            get
            {
                return _soundPath;
            }
            set
            {
                _soundPath = value ?? "";
            }
        }

        private string EncryptedPassword
        {
            get
            {
                return Encrypt(_password);
            }
            set
            {
                _password = Decrypt(value);
            }
        }

        public string Interface
        {
            get
            {
                return _interface;
            }
            set
            {
                _interface = value ?? "";
            }
        }

        public int MailCheckInterval
        {
            get
            {
                return _mailCheckInterval;
            }
            set
            {
                _mailCheckInterval = value;
            }
        }

        public int DaysToRetrieve
        {
            get
            {
                return _daysToRetrieve;
            }
            set
            {
                _daysToRetrieve = value;
            }
        }

        public int CountToRetrieve
        {
            get
            {
                return _countToRetrieve;
            }
            set
            {
                _countToRetrieve = value;
            }
        }

        public bool StartOnApplicationStartup
        {
            get
            {
                return _startOnApplicationStartup;
            }
            set
            {
                _startOnApplicationStartup = value;
            }
        }

        public string NotesUI
        {
            get
            {
                return _ui;
            }
            set
            {
                _ui = value ?? "";
            }
        }

        public string NotesFileUrl
        {
            get
            {
                return _notesFileUrl;
            }
            set
            {
                _notesFileUrl = value ?? "";
            }
        }

        public string XmlUrlSuffix
        {
            get
            {
                return _xmlUrlSuffix;
            }
            set
            {
                _xmlUrlSuffix = value ?? "";
            }
        }

        public string HtmlUrlSuffix
        {
            get
            {
                return _htmlUrlSuffix;
            }
            set
            {
                _htmlUrlSuffix = value ?? "";
            }
        }

        public string ViewMailUrlSuffix
        {
            get
            {
                return _viewMailUrlSuffix;
            }
            set
            {
                _viewMailUrlSuffix = value ?? "";
            }
        }

        public bool Exists
        {
            get
            {
                return _confFile.Exists;
            }
        }

        public void Load()
        {
            IniFileReader ini = new IniFileReader(IniFileReader_ReadItem);
            ini.Read(_confFile.FullName);
        }

        private void IniFileReader_ReadItem(object obj, IniReaderEventArgs args)
        {
            if (!args.IsSectionHeader && !args.IsFullLineComment)
            {
                switch (args.Key)
                {
                    case "Login":
                        if (args.Values.Count > 0) Login = args.Values[0];
                        else Login = string.Empty;
                        break;
                    case "Password":
                        if (args.Values.Count > 0) EncryptedPassword = args.Values[0];
                        else EncryptedPassword = string.Empty;
                        break;
                    case "Interface":
                        if (args.Values.Count > 0) Interface = args.Values[0];
                        else Interface = "xml";
                        break;
                    case "NotesFileUrl":
                        if (args.Values.Count > 0) NotesFileUrl = args.Values[0];
                        else NotesFileUrl = string.Empty;
                        break;
                    case "XmlUrlSuffix":
                        if (args.Values.Count > 0) XmlUrlSuffix = args.Values[0];
                        else XmlUrlSuffix = string.Empty;
                        break;
                    case "HtmlUrlSuffix":
                        if (args.Values.Count > 0) HtmlUrlSuffix = args.Values[0];
                        else HtmlUrlSuffix = string.Empty;
                        break;
                    case "ViewMailUrlSuffix":
                        if (args.Values.Count > 0) ViewMailUrlSuffix = args.Values[0];
                        else ViewMailUrlSuffix = string.Empty;
                        break;
                    case "BrowserOverrideExePath":
                        if (args.Values.Count > 0) BrowserOverrideExePath = args.Values[0];
                        else BrowserOverrideExePath = string.Empty;
                        break;
                    case "Browser":
                        if (args.Values.Count > 0) Browser = args.Values[0];
                        else Browser = "ie";
                        break;
                    case "NotesUI":
                        if (args.Values.Count > 0) NotesUI = args.Values[0];
                        else NotesUI = "webmail";
                        break;
                    case "SoundPath":
                        if (args.Values.Count > 0) SoundPath = args.Values[0];
                        else SoundPath = string.Empty;
                        break;
                    case "MailCheckInterval":
                        if (args.Values.Count > 0) MailCheckInterval = Convert.ToInt32(args.Values[0]);
                        else MailCheckInterval = 60;
                        break;
                    case "DaysToRetrieve":
                        if (args.Values.Count > 0) DaysToRetrieve = Convert.ToInt32(args.Values[0]);
                        else DaysToRetrieve = 7;
                        break;
                    case "CountToRetrieve":
                        if (args.Values.Count > 0) CountToRetrieve = Convert.ToInt32(args.Values[0]);
                        else CountToRetrieve = 50;
                        break;
                    case "StartOnApplicationStartup":
                        if (args.Values.Count > 0) StartOnApplicationStartup = Convert.ToBoolean(args.Values[0]);
                        else StartOnApplicationStartup = false;
                        break;
                }
            }
        }

        public void Save()
        {
            IniFileWriter ini = new IniFileWriter(_confFile);
            ini.WriteKey("Login", Login);
            ini.WriteKey("Password", EncryptedPassword);
            ini.WriteKey("Interface", Interface);
            ini.WriteKey("MailCheckInterval", MailCheckInterval.ToString());
            ini.WriteKey("DaysToRetrieve", DaysToRetrieve.ToString());
            ini.WriteKey("CountToRetrieve", CountToRetrieve.ToString());
            ini.WriteKey("StartOnApplicationStartup", StartOnApplicationStartup.ToString());
            ini.WriteKey("NotesFileUrl", NotesFileUrl);
            ini.WriteKey("XmlUrlSuffix", XmlUrlSuffix);
            ini.WriteKey("HtmlUrlSuffix", HtmlUrlSuffix);
            ini.WriteKey("ViewMailUrlSuffix", ViewMailUrlSuffix);
            ini.WriteKey("Browser", Browser);
            ini.WriteKey("BrowserOverrideExePath", BrowserOverrideExePath);
            ini.WriteKey("NotesUI", NotesUI);
            ini.WriteKey("SoundPath", SoundPath);
            ini.Close();
            _confFile.Refresh();
        }

        public static string Encrypt(string s)
        {
            return Convert.ToBase64String(EncryptDecrypt(System.Text.Encoding.Unicode.GetBytes(s)));
        }

        public static string Decrypt(string s)
        {
            return System.Text.Encoding.Unicode.GetString(EncryptDecrypt(Convert.FromBase64String(s)));
        }

        private static byte[] EncryptDecrypt(byte[] bytes)
        {
            byte[] newbytes = new byte[bytes.Length];

            for (int i = 0; i < bytes.Length; i++)
            {
                byte b = bytes[i];

                byte n = (byte)(b ^ 0xFF);
                byte l = (byte)((n >> 4) & 0x0F);
                byte r = (byte)((n << 4) & 0xF0);
                byte final = (byte)(l | r);
                newbytes[i] = final;
            }

            return newbytes;
        }
    }
}
